package com.seeyon.apps.relocationData.utils;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.seeyon.cap4.form.bean.FormBean;
import com.seeyon.cap4.form.bean.FormFieldBean;
import com.seeyon.cap4.form.bean.FormTableBean;
import com.seeyon.cap4.form.service.CAP4FormManager;
import com.seeyon.ctp.common.AppContext;
import com.seeyon.ctp.common.constants.ApplicationCategoryEnum;
import com.seeyon.ctp.common.ctpenumnew.manager.EnumManager;
import com.seeyon.ctp.common.filemanager.manager.AttachmentManager;
import com.seeyon.ctp.common.po.ctpenumnew.CtpEnumBean;
import com.seeyon.ctp.common.po.ctpenumnew.CtpEnumItem;
import com.seeyon.ctp.organization.bo.V3xOrgAccount;
import com.seeyon.ctp.organization.bo.V3xOrgMember;
import com.seeyon.ctp.organization.manager.OrgManager;
import com.seeyon.ctp.organization.po.OrgUnit;
import com.seeyon.ctp.util.DBAgent;
import com.seeyon.ctp.util.JDBCAgent;
import com.seeyon.ctp.util.Strings;
import com.seeyon.ctp.util.UUIDLong;
import org.apache.commons.dbutils.QueryRunner;
import org.apache.commons.dbutils.handlers.MapHandler;
import org.apache.commons.dbutils.handlers.MapListHandler;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import java.sql.Connection;
import java.sql.SQLException;
import java.sql.Timestamp;
import java.util.*;
import java.util.stream.Collectors;

public class FormUtils {
    private static final Log log = LogFactory.getLog(FormUtils.class);
    private static AttachmentManager attachmentManager;

    public static JSONObject initiatingForm(JSONObject body) throws SQLException {
        log.info("进入创建耗材底表");
        Connection connection = JDBCAgent.getDataSource().getConnection();
        try {
            QueryRunner queryRunner = new QueryRunner();
            connection.setAutoCommit(false);
            Long mainId;
            boolean isUpdate = false;
            OrgManager orgManager = (OrgManager) AppContext.getBean("orgManager");
            CAP4FormManager cap4FormManager = (CAP4FormManager) AppContext.getBean("cap4FormManager");
            // 获取模板编号
            String templateCode = body.getString("templateCode");
            // 获取是否CAP4
            Boolean isCap4 = body.getBoolean("isCap4");
            if (isCap4 == null) {
                isCap4 = true;
            }
            String uniqueKey = body.getString("uniqueKey");
            if (StringUtils.isEmpty(uniqueKey)) {
                return toJson(-1, "uniqueKey不能为空!", null);
            }
            String uniqueValue = body.getString("uniqueValue");
            if (StringUtils.isEmpty(uniqueValue)) {
                return toJson(-1, "unqueValue不能为空!", null);
            }
            // 表单数据
            JSONObject data = body.getJSONObject("data");
            // 获取data主表的
            Map<String, Object> mainData = new HashMap<>();
            // 保存在数据库
            Map<String, Object> saveMainData = new HashMap<>();
            // 主表数据
            if (data.getJSONArray("mainData") == null || data.getJSONArray("mainData").isEmpty()) {
                return toJson(-1, "主表数据不能为空！", null);
            }
            List<Map> mainjsonData = data.getJSONArray("mainData").toJavaList(Map.class);
            Map<Object, List<Map>> map = mainjsonData.stream().collect(Collectors.groupingBy(p -> p.get("name")));
            for (Map temp : mainjsonData) {
                if (temp.get("name") == null) {
                    return toJson(-1, "主表name属性不能为空!", null);
                } else {
                    if (map.get(temp.get("name")).size() > 1) {
                        return toJson(-1, "主表数据name属性重复! name:" + temp.get("name"), null);
                    }
                    mainData.put(temp.get("name").toString(), temp.get("value"));
                }
            }
            // 查询表单
            if (isCap4) {
                // CAP4
                FormBean form = cap4FormManager.getFormByFormCode(templateCode);
                if (form == null) {
                    return toJson(-1, "该模板编号未对应有效的表单!", null);
                }
                // 获取主表字段
                FormTableBean masterTable = form.getMasterTableBean();
                // uniqueKey是否存在
                FormFieldBean uniqueBean = masterTable.getFieldBeanByDisplay(uniqueKey);
                if (uniqueBean == null) {
                    return toJson(-1, "uniqueKey标识的字段不存在!", null);
                }
                // 查询是否为更新
                List<Map<String, Object>> query = queryRunner.query(connection, "SELECT ID FROM "
                                + form.getMasterTableBean().getTableName() + " WHERE " + uniqueBean.getName() + "=?",
                        new MapListHandler(), uniqueValue);
                if (query.size() > 1) {
                    return toJson(-1, "uniqueValue对应的值不唯一!", null);
                } else {
                    if (query.size() == 1) {
                        mainId = Long.valueOf(query.get(0).get("ID").toString());
                        isUpdate = true;
                    } else {
                        mainId = UUID.randomUUID().getLeastSignificantBits();
                    }
                }
                // 获取唯一标识数据
                Object object = saveMainData.get(masterTable.getFieldBeanByDisplay(uniqueKey).getName());
                if (object != null && !uniqueValue.equals(object)) {
                    return toJson(-1, "操作非法,唯一标识的值应该保持一致!", null);
                }
                for (String name : mainData.keySet()) {
                    FormFieldBean fieldBean = null;
                    if ("sort".equals(name)) {
                        FormFieldBean temp = new FormFieldBean();
                        temp.setName("sort");
                        fieldBean = temp;
                    } else {
                        fieldBean = masterTable.getFieldBeanByDisplay(name);
                    }
                    if (fieldBean == null) {
                        return toJson(-1, "主表name对应的字段不存在! name:" + name, null);
                    } else {
                        // 为主表数据赋值
                        String inputType = fieldBean.getInputType();

                        // modify by  [适配选人、选部门、选单位、下拉框、上传附件控件] start
                        Object value = mainData.get(name);
                        if("member".equals(inputType)) {
                            V3xOrgMember member = orgManager.getMemberByLoginName(value.toString());
                            if(member != null) {
                                mainData.put(name, member.getId().toString());
//		            			value = member.getId().toString();
                            }
                        } else if("department".equals(inputType)) {
                            if(value.toString().indexOf("-") > -1) {
                                String deptId = getDeptIdByCode(value.toString());
                                if(deptId != null) {
//		            				value = deptId;
                                    mainData.put(name, deptId);
                                }
                            }
                        } else if("multimember".equals(inputType)) {
                            if(Strings.isNotBlank(value.toString())) {
                                String[] memberLoginNames = value.toString().split(",");
                                V3xOrgMember member = null;
                                String memberIds = "";
                                for(String loginName : memberLoginNames) {
                                    loginName = loginName.trim();
                                    member = orgManager.getMemberByLoginName(loginName);
                                    if(member != null) {
                                        memberIds += member.getId().toString() + ",";
                                    }
                                }
                                if(Strings.isNotBlank(memberIds)) {
                                    memberIds = memberIds.substring(0, memberIds.length()-1);
//		            				value = memberIds;
                                    mainData.put(name, memberIds);
                                }
                            }
                        } else if("account".equals(inputType)) {
                            String accountId = getAccountIdByCode(value.toString());
                            if(Strings.isNotBlank(accountId)) {
//		            			value = accountId;
                                mainData.put(name, accountId);
                            }
                        } else if("attachment".equals(inputType) || "image".equals(inputType)){
                            Long uuid = UUIDLong.longUUID();
                            String[] strs = value.toString().split(",");
                            List<Long> ids = new ArrayList<Long>();
                            for(int i = 0; i < strs.length; ++i){
                                if(Strings.isNotBlank(strs[i])) {
                                    ids.add(Long.valueOf(strs[i]));
                                }
                            }

                            Long[] idsArray = new Long[ids.size()];
                            for(int i=0;i<ids.size();i++) {
                                idsArray[i] = ids.get(i);
                            }
                            String re = getAttachmentManager().create(idsArray, ApplicationCategoryEnum.cap4Form, mainId, uuid);
//	                        value = uuid.toString();
                            mainData.put(name, uuid.toString());
                        }else if("select".equals(inputType)) {
                            long enumId = fieldBean.getEnumId();
                            EnumManager enumManagerNew = (EnumManager) AppContext.getBean("enumManagerNew");
                            CtpEnumBean enumBean = enumManagerNew.getEnum(enumId);
                            List<CtpEnumItem> items = enumBean.getItems();
                            for (CtpEnumItem item : items) {
                                if(item.getShowvalue().equals(value.toString())) {
                                    mainData.put(name, item.getId());
                                    break;
                                }
                            }
                        }
                        // modify by  [适配选人、选部门、选单位、下拉框、上传附件控件] end

                        // TODO 日期 ORACLE 的日期处理可能不同,这个自行处理,这儿可以根据控件类型设置对应的�?
                        saveMainData.put(fieldBean.getName(), mainData.get(name));
                    }
                }


                List<FormTableBean> subTables = form.getSubTableBean();
                // 封装从表数据
                Map<String, String> subTableNames = new HashMap<>();
                for (FormTableBean subTable : subTables) {
                    subTableNames.put(subTable.getDisplay(), subTable.getTableName());
                }
                Map<String, List<List<Map<String, Object>>>> saveSubData = new HashMap<>();
                if (data.getJSONArray("subData") == null) {
                    data.put("subData", new ArrayList<JSONObject>());
                }
                List<JSONObject> subData = data.getJSONArray("subData").toJavaList(JSONObject.class);
                Map<Object, List<JSONObject>> subNames = subData.stream()
                        .collect(Collectors.groupingBy(p -> p.get("name")));
//				for (Object subName : subNames.keySet()) {
//					List<JSONObject> ss = subNames.get(subName);
//					if (subNames.get(subName).size() > 1) {
//						return buildMsg(-1, "请统一明细表数据!明细表重复! name:" + subName, null);
//					}
//				}
                for (JSONObject subDatum : subData) {
                    String name = subDatum.getString("name");
                    List<List<Map<String, Object>>> dataContent = new ArrayList<>();
                    if (!subTableNames.containsKey(name)) {
                        return toJson(-1, "明细表name属性无效,不存在该名称的明细表! name:" + name, null);
                    } else {
                        FormTableBean subTable = form.getTableByTableName(subTableNames.get(name));
                        Map<String, FormFieldBean> fields = new HashMap<>();
                        for (FormFieldBean field : subTable.getFields()) {
                            fields.put(field.getDisplay(), field);
                        }
                        // 添加排序号
                        FormFieldBean sortBean = new FormFieldBean();
                        sortBean.setName("sort");
                        FormFieldBean idBean = new FormFieldBean();
                        idBean.setName("id");
                        fields.put("sort", sortBean);
                        fields.put("id", idBean);
                        // 获取content数据
                        List<JSONArray> content = subDatum.getJSONArray("content").toJavaList(JSONArray.class);
                        Set<Object> ids = new HashSet<>();
                        for (JSONArray con : content) {
                            List<JSONObject> temp = con.toJavaList(JSONObject.class);
                            Map<Object, List<JSONObject>> collect = temp.stream()
                                    .collect(Collectors.groupingBy(p -> p.get("name")));
                            for (Object o : collect.keySet()) {
                                if (collect.get(o).size() > 1) {
                                    return toJson(-1, "明细表数据域name值不能重复! 明细表name:" + name + ",字段name:" + o, null);
                                }
                            }
                            List<Map<String, Object>> saveSubDataList = new ArrayList<>();
                            for (JSONObject o : temp) {
                                // 不允许有重复的数据出现在明细表数据中！
                                Map<String, Object> tem = new HashMap<>();
                                String key = o.getString("name");
                                if (key == null) {
                                    return toJson(-1, "明细表数据域name值不 能为空!", null);
                                }
                                if (!fields.containsKey(key)) {
                                    return toJson(-1, "明细表字段name属性无效!不存在该名称的字段,name:" + key + ",明细表name:" + name, null);
                                }
                                FormFieldBean fieldBean = fields.get(key);
                                if ("id".equals(fieldBean.getName())) {
                                    if (ids.contains(o.get("value"))) {
                                        return toJson(-1, "明细表数据域name值为id不能重复!", null);
                                    }
                                    ids.add(o.get("value"));
                                }
                                // TODO 日期 ORACLE 的日期处理可能不同,这个自行处理,这儿可以根据控件类型设置对应的值
                                String inputType = fieldBean.getInputType();

                                // modify by  [适配选人、选部门、选单位、下拉框、上传附件控件] start
                                Object value = o.get("value");
                                if("member".equals(inputType)) {
                                    V3xOrgMember member = orgManager.getMemberByLoginName(value.toString());
                                    if(member != null) {
                                        value = member.getId().toString();
                                    }
                                } else if("department".equals(inputType)) {
                                    if(value.toString().indexOf("-") > -1) {
                                        String deptId = getDeptIdByCode(value.toString());
                                        if(deptId != null) {
                                            value = deptId;
                                        }
                                    }
                                } else if("multimember".equals(inputType)) {
                                    if(Strings.isNotBlank(value.toString())) {
                                        String[] memberLoginNames = value.toString().split(",");
                                        V3xOrgMember member = null;
                                        String memberIds = "";
                                        for(String loginName : memberLoginNames) {
                                            loginName = loginName.trim();
                                            member = orgManager.getMemberByLoginName(loginName);
                                            if(member != null) {
                                                memberIds += member.getId().toString() + ",";
                                            }
                                        }
                                        if(Strings.isNotBlank(memberIds)) {
                                            memberIds = memberIds.substring(0, memberIds.length()-1);
                                            value = memberIds;
                                        }
                                    }
                                } else if("account".equals(inputType)) {
                                    String accountId = getAccountIdByCode(value.toString());
                                    if(Strings.isNotBlank(accountId)) {
                                        value = accountId;
                                    }
                                } else if("attachment".equals(inputType) || "image".equals(inputType)){
                                    Long uuid = UUIDLong.longUUID();
                                    String[] strs = value.toString().split(",");
                                    List<Long> ids_1 = new ArrayList<Long>();
                                    for(int i = 0; i < strs.length; ++i){
                                        if(Strings.isNotBlank(strs[i])) {
                                            ids_1.add(Long.valueOf(strs[i]));
                                        }
                                    }

                                    Long[] idsArray = new Long[ids_1.size()];
                                    for(int i=0;i<ids_1.size();i++) {
                                        idsArray[i] = ids_1.get(i);
                                    }
                                    String re = getAttachmentManager().create(idsArray, ApplicationCategoryEnum.cap4Form, mainId, uuid);
                                    value = uuid.toString();
                                }else if("select".equals(inputType)) {
                                    long enumId = fieldBean.getEnumId();
                                    EnumManager enumManagerNew = (EnumManager) AppContext.getBean("enumManagerNew");
                                    CtpEnumBean enumBean = enumManagerNew.getEnum(enumId);
                                    List<CtpEnumItem> items = enumBean.getItems();
                                    for (CtpEnumItem item : items) {
                                        if(item.getShowvalue().equals(value.toString())) {
                                            value = item.getId();
                                            break;
                                        }
                                    }
                                }
//								tem.put(fieldBean.getName(), o.get("value"));
                                tem.put(fieldBean.getName(), value);
                                // modify by  [适配选人、选部门、选单位、下拉框、上传附件控件] end

                                saveSubDataList.add(tem);
                            }
                            dataContent.add(saveSubDataList);
                        }
                    }
                    saveSubData.put(subTableNames.get(name), dataContent);
                }


                V3xOrgAccount member;
                if (!isUpdate) {
                    // 新增是必须指定唯一标识的值
                    if (object == null) {
                        saveMainData.put(masterTable.getFieldBeanByDisplay(uniqueKey).getName(), uniqueValue);
                    }
                    isUpdate = false;
                    // 获取登录人员名称
                    String loginName = body.getString("loginName");
                    if (Strings.isEmpty(loginName)) {
                        return toJson(-1, "当表单数据是新增时,创建表单人员的loginName不能为空!", null);
                    }
                    member = orgManager.getAccountByLoginName(loginName);
                    if (member == null) {
                        return toJson(-1, "loginName无效,无法找到对应的人员!", null);
                    }
//					mainId = UUID.randomUUID().getLeastSignificantBits();
                    // 初始化主表数据
                    String insertSql = "insert into " + masterTable.getTableName()
                            + " (id,state,start_member_id,start_date,approve_member_id,approve_date,finishedflag,ratifyflag,ratify_member_id,ratify_date,sort,modify_member_id,modify_date) values(?,?,?,?,?,?,?,?,?,?,?,?,?)";
                    queryRunner.execute(connection, insertSql, mainId, 1, member.getId(),
                            new Timestamp(System.currentTimeMillis()), 0, null, 0, 0, 0, null, 0, member.getId(),
                            new Timestamp(System.currentTimeMillis()));
                    // 初始化ctp_content_all
                    String initContentSql = " insert into ctp_content_all(id,create_date,create_id,modify_date,modify_id,module_type,module_id,content_type,content_data_id,content_template_id,sort) values(?,?,?,?,?,?,?,?,?,?,?)";
                    queryRunner.execute(connection, initContentSql, UUID.randomUUID().getLeastSignificantBits(),
                            new Timestamp(System.currentTimeMillis()), member.getId(), new Timestamp(System.currentTimeMillis()), member.getId(), 42, mainId, 20, mainId,
                            form.getId(), 0);
                }
                saveData(mainId, connection, saveMainData, masterTable.getTableName());
                // 更新从表
                for (String tableName : saveSubData.keySet()) {
                    List<List<Map<String, Object>>> lists = saveSubData.get(tableName);
                    //if (isOverrideSub) {
                    //    queryRunner.execute(connection, "delete from " + tableName + " where formmain_id = ?", mainId);
                    //}
                    // 查询数据是否存在
                    for (List<Map<String, Object>> list : lists) {
                        List<Map<String, Object>> id = list.stream().filter(p -> null != p.get("id"))
                                .collect(Collectors.toList());
                        long subId;
                        // 说明有Id的值有效,进行查询
                        if (id.size() == 1) {
                            Map<String, Object> row = queryRunner.query(connection,
                                    "select * from " + tableName + " where id = ?", new MapHandler(),
                                    id.get(0).get("id"));
                            subId = Long.parseLong(String.valueOf(id.get(0).get("id")));
                            if (row == null || row.isEmpty()) {
                                // 指定ID新增
                                queryRunner.execute(connection,
                                        "insert into " + tableName + "(id,formmain_id) values(?,?)", subId, mainId);
                            }
                        } else {
                            // 随机生成ID
                            subId = UUID.randomUUID().getLeastSignificantBits();
                            queryRunner.execute(connection, "insert into " + tableName + "(id,formmain_id) values(?,?)",
                                    subId, mainId);
                        }
                        // 实现更新操作
                        for (Map<String, Object> col : list) {
                            saveData(subId, connection, col, tableName);
                        }
                    }
                }
                connection.commit();
                if (isUpdate) {
                    return toJson(1, "更新数据成功!", null);
                } else {
                    return toJson(1, "新增数据成功!", null);
                }
            }else{
                log.info("暂不支持CAP3");
            }
        } catch (Exception e) {
            connection.rollback();
            log.error("发起台账异常！！！",e);
            return toJson(-1, "调用接口异常! e:" + e.getMessage(), null);
        } finally {
            connection.close();
        }
        return null;
    }

    public static JSONObject toJson(Object code,String msg,Object data){
        JSONObject param = new JSONObject();
        param.put("code",code);
        param.put("msg",msg);
        param.put("data",data);
        return param;
    }

    private static String getAccountIdByCode(String code) {
        String accountId = null;
        Map<String, Object> pars = new HashMap<String, Object>();
        pars.put("unitCode", code);
        List<OrgUnit> unitList = DBAgent.find("from OrgUnit where code=:unitCode and type='Account' and enable=true", pars);
        if(unitList!=null && unitList.size()>0) {
            accountId = unitList.get(0).getId().toString();
        }
        return accountId;
    }

    private static String getDeptIdByCode(String code) {
        String deptId = null;
        Map<String, Object> pars = new HashMap<String, Object>();
        pars.put("deptCode", code);
        List<OrgUnit> unitList = DBAgent.find("from OrgUnit where code=:deptCode and type='Department' and enable=true", pars);
        if(unitList!=null && unitList.size()>0) {
            deptId = unitList.get(0).getId().toString();
        }
        return deptId;
    }

    public static void saveData(Long mainId, Connection connection, Map<String, Object> data, String mainTaleName)
            throws SQLException {
        QueryRunner queryRunner = new QueryRunner();
        // 更新主表
        StringBuilder sql = new StringBuilder("update " + mainTaleName + " set ");
        Set<String> sets = data.keySet();
        for (String set : sets) {
            // 忽略空字段
            if (data.get(set) == null) {
                continue;
            }
            sql.append(set).append(" = '").append(data.get(set)).append("',");
        }
        sql.deleteCharAt(sql.length() - 1);
        sql.append(" where id = '").append(mainId).append("'");
        queryRunner.execute(connection, sql.toString());
    }

    public static AttachmentManager getAttachmentManager(){
        if(attachmentManager==null){
            attachmentManager= (AttachmentManager)AppContext.getBean("attachmentManager");
        }
        return attachmentManager;
    }


}
